package com.gopay.checkorder.dao.impl;

import com.gopay.checkorder.dao.BankReturnMsgForFusedDAO;
import com.gopay.checkorder.dao.BankSentinelInfoDAO;
import com.gopay.checkorder.dao.BisTimingFuseDao;
import com.gopay.common.base.dao.impl.BaseDAOImpl;
import com.gopay.common.domain.bank.bcdl.BisBankReturnMsgForFused;
import com.gopay.common.domain.bank.bcdl.BisBankSentinelInfo;
import com.gopay.common.domain.bank.bcdl.BisTimingFuse;
import com.gopay.common.order.dao.CommonQueryDAO;
import com.gopay.common.util.DateUtils;
import com.gopay.common.util.StringTools;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Repository(value = "bankSentinelInfoDAO")
public class BankSentinelInfoDAOImpl extends BaseDAOImpl<BisBankSentinelInfo, String> implements BankSentinelInfoDAO {

	@Resource(name = "commonQueryDAO")
	private CommonQueryDAO commonQueryDAO;

	@Resource(name = "bisTimingFuseDao")
	private BisTimingFuseDao bisTimingFuseDao;
	/**
	 * 通过熔断器编号查找熔断状态
	 * @param sentinelId
	 * @return
	 */
	@Override
	public Boolean findByStlmEx(String sentinelId) {
		StringBuilder sqlBuilder = new StringBuilder();
		sqlBuilder.append("SELECT SENTINEL_CODE, STLM_EX, IS_FUSED, BANK_CODE, FUSED_TS, FUSED_REASON ");
		sqlBuilder.append(" FROM BIS_BANK_SENTINEL_INFO WHERE 1=1 ");
		sqlBuilder.append(" AND SENTINEL_CODE = :sentinelId ");
		Map<String,Object> paramMap = new HashMap<>();
		paramMap.put("sentinelId", sentinelId);
		try {
			List<Object[]> sentinelInfos = commonQueryDAO.findBySql(sqlBuilder.toString(), paramMap);
			if (null != sentinelInfos && sentinelInfos.size() > 0) {
				Object[] obj = sentinelInfos.get(0);
				String fusedStr = StringTools.checkNulltoString(obj[2]);
				int ifFused = Integer.parseInt(fusedStr);
                return ifFused == 0 ? false:true;
            } else {
				throw new RuntimeException("查询熔断器状态异常，数据库未查询到该熔断器，sentinelId:"+sentinelId);
			}
		} catch (Exception e) {
			e.printStackTrace();
		    throw new RuntimeException("查询熔断器状态异常，sentinelId:"+sentinelId);
		}
	}

	@Override
	@Transactional
	public boolean updateSentinel(int flag, int isFused, String sentinelId, String msg, String gopayOrderId) {

		boolean boo = true;
		try {
			StringBuilder sqlBuilder = new StringBuilder();
			sqlBuilder.append("UPDATE BIS_BANK_SENTINEL_INFO ");
			sqlBuilder.append(" SET IS_FUSED = :ifFused, FUSED_REASON = :fusedReason, FUSED_TS = :fusedTs WHERE ");
			sqlBuilder.append(" SENTINEL_CODE = :sentinelId  ");
			Map<String,Object> paramMap = new HashMap<>();
			paramMap.put("sentinelId", sentinelId);
			paramMap.put("ifFused", isFused);
			String fusedReason = "";
			if (0 == flag) {//如果为手工操作熔断
				if (1 == isFused) {
					fusedReason = "手工熔断";
				}
			} else if (2 == flag) {
					fusedReason = "付款任务超时未处理完，做熔断处理";
			}
			else if (3 == flag) {
					fusedReason = "插入防重表异常";
			}else {
				if (gopayOrderId.startsWith("PacketNo")) {
					fusedReason = msg + ", " + gopayOrderId;
				} else {
					fusedReason = msg + ", gopayOrderId:" + gopayOrderId;
				}
			}
			paramMap.put("fusedReason", fusedReason);
			paramMap.put("fusedTs", new Date());

			this.updateBySql(sqlBuilder.toString(), paramMap);
		} catch (Exception e) {
			boo = false;
		}
		return boo;
	}

	@Override
	@Transactional
	public void updateSentinelAndTimeFuse(int isFused, String sentinelId,Long sq) {//isFused：0未熔断，，1熔断
		BisTimingFuse bisTimingFuse = bisTimingFuseDao.find(BisTimingFuse.class, sq);
		Date current = new Date();
		StringBuilder sqlBuilder = new StringBuilder();
		sqlBuilder.append("UPDATE BIS_BANK_SENTINEL_INFO ");
		sqlBuilder.append(" SET IS_FUSED = :ifFused, FUSED_REASON = :fusedReason, FUSED_TS = :fusedTs WHERE ");
		sqlBuilder.append(" SENTINEL_CODE = :sentinelId  ");
		Map<String, Object> paramMap = new HashMap<>();
		paramMap.put("sentinelId", sentinelId);
		paramMap.put("ifFused", isFused);
		bisTimingFuse.setLastUpdateTs(current);
		if (isFused == 1) {//若为1视为执行中0视为已执行
			bisTimingFuse.setTimingStatus(BisTimingFuse.TimingStatus.EXECUTING.getCode());
			paramMap.put("fusedReason", "定时熔断");
		} else {
			bisTimingFuse.setTimingStatus(BisTimingFuse.TimingStatus.EXECUTED.getCode());
			bisTimingFuse.setRealEndTs(current);
			paramMap.put("fusedReason", "");
		}
		paramMap.put("fusedTs", current);
		this.updateBySql(sqlBuilder.toString(), paramMap);//更新熔断总表
		bisTimingFuseDao.update(bisTimingFuse);//更新定时熔断表
	}
}
